package net.huashitong.ssydt.provider.task.service;


import net.huashitong.ssydt.exceptions.ServiceException;
import net.huashitong.ssydt.money.constant.OperationEnum;
import net.huashitong.ssydt.provider.constant.SsydtConsts;
import net.huashitong.ssydt.provider.money.service.SsMoneyGoldService;
import net.huashitong.ssydt.provider.task.dto.CardBagDTO;
import net.huashitong.ssydt.provider.utils.date.DateUtils;
import net.huashitong.ssydt.task.constant.TaskConsts;
import net.huashitong.ssydt.task.entity.*;
import net.huashitong.ssydt.task.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href="mailto:yhy23456@163.com">huiyang.yu</a>
 * @since 2018.01.10
 */
@Service
public class TaskServiceImpl implements TaskService {

    private SsTaskCardService ssTaskCardService;

    private SsTaskCardRecordService ssTaskCardRecordService;

    private SsTaskMyCardService ssTaskMyCardService;

    private SsTaskMedalService ssTaskMedalService;

    private SsTaskMedalRecordService ssTaskMedalRecordService;

    private SsTaskTaskService ssTaskTaskService;

    private SsTaskTaskRecordService ssTaskTaskRecordService;

    private SsMoneyGoldService ssMoneyGoldService;

    @Autowired
    public TaskServiceImpl(SsTaskCardService ssTaskCardService,
                           SsTaskCardRecordService ssTaskCardRecordService,
                           SsTaskMyCardService ssTaskMyCardService,
                           SsTaskMedalService ssTaskMedalService,
                           SsTaskMedalRecordService ssTaskMedalRecordService,
                           SsTaskTaskService ssTaskTaskService,
                           SsTaskTaskRecordService ssTaskTaskRecordService,
                           SsMoneyGoldService ssMoneyGoldService) {
        this.ssTaskCardService = ssTaskCardService;
        this.ssTaskCardRecordService = ssTaskCardRecordService;
        this.ssTaskMyCardService = ssTaskMyCardService;
        this.ssTaskMedalService = ssTaskMedalService;
        this.ssTaskMedalRecordService = ssTaskMedalRecordService;
        this.ssTaskTaskService = ssTaskTaskService;
        this.ssTaskTaskRecordService = ssTaskTaskRecordService;
        this.ssMoneyGoldService = ssMoneyGoldService;
    }

    @Override
    public List<YearCardBagVO> getCardBags(CardBagInVO inVO, String userId) {
        List<YearCardBagVO> yearsList = new ArrayList<>();
        List<CardBagOutVO> cardBagOutVOS = new ArrayList<>();
        List<CardBagDTO> dtos = ssTaskCardService.queryGroupByYearsWithMonths(inVO);
        String years = null;
        for (CardBagDTO dto : dtos) {
            int myCardNumber = ssTaskCardRecordService.countByYearMonthsWithUserId(dto.getYearMonths(), userId);
            if (years == null) {
                years = dto.getYears();
            }
            if (!dto.getYears().equals(years)) {
                addForYearsList(years, cardBagOutVOS, yearsList);
                years = dto.getYears();
                cardBagOutVOS = new ArrayList<>();
            }
            CardBagOutVO vo = new CardBagOutVO();
            BeanUtils.copyProperties(dto, vo);
            vo.setMyCardNumber(myCardNumber);
            cardBagOutVOS.add(vo);
        }
        if (!cardBagOutVOS.isEmpty()) {
            addForYearsList(years, cardBagOutVOS, yearsList);
        }
        return yearsList;
    }

    /**
     * 添加到年份列表中
     *
     * @param years
     * @param cardBagOutVOS
     * @param yearsList
     */
    private void addForYearsList(String years, List<CardBagOutVO> cardBagOutVOS, List<YearCardBagVO> yearsList) {
        YearCardBagVO yearCardBagVO = new YearCardBagVO();
        yearCardBagVO.setYears(years);
        yearCardBagVO.setList(cardBagOutVOS);
        yearsList.add(yearCardBagVO);
    }

    @Override
    public CardInfoVO getCardInfo(String userId) {
        SsTaskMyCard ssTaskMyCard = ssTaskMyCardService.getAutoCreateByUserId(userId);
        CardInfoVO vo = new CardInfoVO();
        BeanUtils.copyProperties(ssTaskMyCard, vo);
        int number = ssTaskCardService.countAll();
        vo.setNotCardNumber(number - ssTaskMyCard.getCardNumber());
        return vo;
    }

    @Override
    public List<CardsOutVO> getCards(String userId, String yearMonths) {
        List<SsTaskCard> ssTaskCards = ssTaskCardService.findByYearMonths(yearMonths);
        List<CardsOutVO> listSequence = new ArrayList<>();//已经获得列表
        List<CardsOutVO> list = new ArrayList<>();//未获得列表
        for (SsTaskCard ssTaskCard : ssTaskCards) {
            CardsOutVO outVO = new CardsOutVO(ssTaskCard);
            SsTaskCardRecord ssTaskCardRecord = ssTaskCardRecordService
                    .getByCardIdWihUserId(ssTaskCard.getId(), userId);
            if (ssTaskCardRecord != null) {
                boolean isRead = ssTaskCardRecord.getIsRead() != null
                        && ssTaskCardRecord.getIsRead().equals(SsydtConsts.IsRead.READ);
                outVO.setIsRead(isRead);
                outVO.setIsShow(true);
                listSequence.add(outVO);
            } else {
                list.add(outVO);
            }
        }
        listSequence.addAll(list);
        return listSequence;
    }

    @Override
    public Integer getCardsNumber(String userId) {
        return ssTaskCardRecordService.countByUserIdWithReadState(userId, SsydtConsts.IsRead.UN_READ);
    }

    @Override
    public boolean postCardsQuestionId(String userId, Long questionId) {
        boolean success = false;
        SsTaskCard ssTaskCard = ssTaskCardService.getByQuestionId(questionId);
        if (ssTaskCard != null) {
            SsTaskCardRecord record = ssTaskCardRecordService.getByCardIdWihUserId(ssTaskCard.getId(), userId);
            if (record == null) {
                record = new SsTaskCardRecord();
                record.setYearMonths(ssTaskCard.getYearMonths());
                record.setCardId(ssTaskCard.getId());
                record.setUserId(userId);
                record.setIsRead(SsydtConsts.IsRead.UN_READ);
                ssTaskCardRecordService.insert(record);
                //增加我的卡包数并计算附加分
                addMyCardAndCalculationAdditionalScore(userId);
                success = true;
            }
        }
        return success;
    }


    @Override
    public void putCardsByCardId(String userId, Long cardId) {
        SsTaskCardRecord record = ssTaskCardRecordService.getByCardIdWihUserId(cardId, userId);
        if (record != null) {
            record.setIsRead(SsydtConsts.IsRead.READ);
            ssTaskCardRecordService.updateByPrimaryKey(record);
        }
    }

    @Override
    public void putCards(String userId) {
        ssTaskCardRecordService.updateReadStateToRead(userId);
    }

    @Override
    public List<TaskMedalVO> getMedals(String userId) {
        List<TaskMedalVO> list = new ArrayList<>();
        List<SsTaskMedal> ssTaskMedals = ssTaskMedalService.findSequenceAsc();
        List<SsTaskMedalRecord> records = ssTaskMedalRecordService.findByUserId(userId);
        for (SsTaskMedal ssTaskMedal : ssTaskMedals) {
            boolean light = false;
            for (int i = 0; i < records.size(); i++) {
                SsTaskMedalRecord record = records.get(i);
                if (record != null && ssTaskMedal.getId().equals(record.getMedalId())) {
                    light = true;
                    records.remove(i);
                    break;
                }
            }
            TaskMedalVO vo = new TaskMedalVO(ssTaskMedal);
            vo.setLight(light);
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<TasksVO> getTasks(String userId) {
        List<SsTaskTask> ssTaskTask = ssTaskTaskService.findByEnable();
        List<TasksVO> list = new ArrayList<>();
        for (SsTaskTask taskTask : ssTaskTask) {
            SsTaskTaskRecord ssTaskTaskRecord = ssTaskTaskRecordService
                    .getNowDateAutoCreateByUserIdWidthTaskId(userId, taskTask.getId());
            TasksVO vo = new TasksVO(taskTask, ssTaskTaskRecord);
            list.add(vo);
        }
        return list;
    }

    @Override
    public void postTasks(String userId, Long taskRecordId) {
        SsTaskTaskRecord ssTaskTaskRecord = ssTaskTaskRecordService.selectByPrimaryKey(taskRecordId);
        if (ssTaskTaskRecord == null || !ssTaskTaskRecord.getUserId().equals(userId)) {
            throw new ServiceException("非法操作");
        }
        switch (ssTaskTaskRecord.getStatus()) {
            case "02":
                ssMoneyGoldService.modifyAndRecordBill(userId, OperationEnum.ADD,
                        ssTaskTaskRecord.getGoldNumber(), "完成任务奖励");
                ssTaskTaskRecord.setStatus("03");
                ssTaskTaskRecordService.updateByPrimaryKey(ssTaskTaskRecord);
                break;
            case "01":
                throw new ServiceException("任务未完成");
            case "03":
                throw new ServiceException("奖励已领取");
            default:
                throw new ServiceException("非法操作");
        }

    }

    @Override
    public Boolean getSign(String userId) {
        SsTaskTaskRecord ssTaskTaskRecord = ssTaskTaskRecordService
                .getNowDateAutoCreateByUserIdWidthTaskId(userId, 1L);
        if (ssTaskTaskRecord.getStatus().equals("01")) {
            return false;
        }
        return true;
    }

    @Override
    public long postSign(String userId) {
        String description = "签到奖励";
        SsTaskTaskRecord ssTaskTaskRecord = ssTaskTaskRecordService
                .getNowDateAutoCreateByUserIdWidthTaskId(userId, 1L);
        Long goldNumber = ssTaskTaskRecord.getGoldNumber();
        if (ssTaskTaskRecord.getStatus().equals("01")) {
            //执行签到
            int number = 1;
            SsTaskTaskRecord old = ssTaskTaskRecordService
                    .getByUserIdWidthTaskIdWidthBelongDate(userId, 1L, DateUtils.getPastDayStr(DateUtils.getDate(), -1));
            if (old != null) {
                number = old.getNumber() + 1;
            }
            if (number >= 3) {
                description = "签到3天及以上奖励";
                SsTaskTask ssTaskTask = ssTaskTaskService.selectByPrimaryKey(ssTaskTaskRecord.getTaskId());
                goldNumber += ssTaskTask.getAdditionalGoldNumber();
            }
            ssTaskTaskRecord.setGoldNumber(goldNumber);
            ssTaskTaskRecord.setNumber(number);
            ssTaskTaskRecord.setStatus("03");
            ssTaskTaskRecordService.updateByPrimaryKey(ssTaskTaskRecord);

            //奖励金币
            ssMoneyGoldService.modifyAndRecordBill(userId, OperationEnum.ADD,
                    goldNumber, description);
        }
        return goldNumber;
    }

    /**
     * 增加我的卡包数并计算附加分
     *
     * @param userId
     */
    private void addMyCardAndCalculationAdditionalScore(String userId) {
        //增加我的卡包数
        SsTaskMyCard ssTaskMyCard = ssTaskMyCardService.getAutoCreateByUserId(userId);
        ssTaskMyCard.setCardNumber(ssTaskMyCard.getCardNumber() + 1);
        ssTaskMyCardService.updateByPrimaryKey(ssTaskMyCard);
        //计算附加分
        List<SsTaskCardRecord> ssTaskCardRecords = ssTaskCardRecordService.findCardRecordByUserId(userId);
        if (!ssTaskCardRecords.isEmpty()) {
            List<Long> ids = new ArrayList<>();
            for (SsTaskCardRecord ssTaskCardRecord : ssTaskCardRecords) {
                ids.add(ssTaskCardRecord.getCardId());
            }
            List<SsTaskCard> ssTaskCards = ssTaskCardService.findByIdInList(ids);
            int totalStarLevel = 0;
            for (SsTaskCard ssTaskCard : ssTaskCards) {
                totalStarLevel += ssTaskCard.getStarLevel();
            }
            BigDecimal additionalScore = BigDecimal.valueOf(totalStarLevel)
                    .multiply(TaskConsts.BASE_CARD_STAR_SCORE).setScale(3, BigDecimal.ROUND_DOWN);
            if (additionalScore.compareTo(TaskConsts.MAX_CARD_STAR_SCORE) > 0) {
                additionalScore = TaskConsts.MAX_CARD_STAR_SCORE;
            }
            ssTaskMyCard.setAddScore(additionalScore);
            ssTaskMyCardService.updateByPrimaryKey(ssTaskMyCard);
        }

    }
}
